package com.lumlord.service;

import com.lumlord.common.annotation.Api;
import com.lumlord.common.domain.LumlordApi;
import com.lumlord.common.domain.log.ConnectLog;
import com.lumlord.common.domain.log.HeartbeatLog;
import com.lumlord.common.domain.log.monitor.Breakdown;
import com.lumlord.common.domain.log.monitor.InterfaceInfo;
import com.lumlord.common.domain.log.monitor.SystemLog;
import com.lumlord.common.exception.BusinessException;
import com.lumlord.common.shiro.config.JwtAuthFilter;
import com.lumlord.common.shiro.util.ShiroUtils;
import com.lumlord.common.spring.RequestJsonBody;
import com.lumlord.common.web.WebSocket;
import com.lumlord.util.AccessAddressUtil;
import com.lumlord.util.DateUtils;
import com.lumlord.util.JdbcTemplateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.method.HandlerMethod;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;

/**
 * 日志存储公共类
 */
@Service
public class LumlordLogService {

    /** 故障类型（1设备故障；2通讯故障；3回路故障；4灯具效果故障；5其他故障）**/
    public enum  BreakType{
        SBGZ,
        TXGZ,
        HLGZ,
        DXGZ,
        QTGZ
    }
    /** 故障等级（1重大；2严重；3轻度；） **/
    public enum  BreakLevel{
        ZD,
        YZ,
        QD
    }
    /** 节点状态（1在线；2离线，发生的时候的状态） **/
    public enum  BreakNodeStatus{
        ZX,
        LX
    }
    /** 操作状态（1正常；2系统异常；3业务异常；4安全异常） **/
    public enum SystemStatus{
        ZC,
        XTYC,
        YWYC,
        AQYC
    }

    /** 插入连接记录表 ***/
    private boolean insertConnectLog(ConnectLog connectLog) throws BusinessException {
       return jdbcTemplateUtils.save(connectLog);
    }
    /**
     * 插入连接记录表
     * @param code 方法编号
     * @param arg 协议
     * @param rec 接收对象
     * @param nodeid 节点编号
     * @param resp 消息
     * @param nodename 节点名称
     * @param password 登入密码
     * @param remark 备注
     * @return
     * @throws BusinessException
     */
    public boolean insertConnectLog(String code, String arg, String rec, String nodeid, String resp, String nodename, String password, String remark)throws BusinessException {
        ConnectLog connectLog = new ConnectLog();
        connectLog.setCode(code);
        connectLog.setArg(arg);
        connectLog.setRec(rec);
        connectLog.setNodeid(nodeid);
        connectLog.setResp(resp);
        connectLog.setNodename(nodename);
        connectLog.setPassword(password);
        connectLog.setRemark(remark);
        return  insertConnectLog(connectLog);
    }
    /**
     * @param request
     * @param systemStatus 系统异常状态
     * @return
     */
    public boolean instertSystemLog(HttpServletRequest request,HttpServletResponse response, SystemStatus systemStatus,String desc) throws BusinessException {
        SystemLog systemLog = new SystemLog();
        HandlerMethod handlerMethod =  jwtAuthFilter.getMethod(request,response);
        if(handlerMethod!=null){
            Api parentApi =  AnnotatedElementUtils.findMergedAnnotation(handlerMethod.getBean().getClass(), Api.class);
            Api api = AnnotatedElementUtils.findMergedAnnotation(handlerMethod.getMethod(), Api.class);
            String name = null;
            if(null != parentApi){
                name = parentApi.moduleName();
            }
            if(null != api){
                name += name==null?api.moduleName():">>"+api.actionName();
                systemLog.setOperationType(name);
                systemLog.setDescription(desc==null?api.moduleName():desc);
            }
             systemLog.setMethod(handlerMethod.getMethod().toString());
        }
        systemLog.setOperationStatus(systemStatus);
        systemLog.setUrl(request.getMethod()+":" +request.getRequestURL());
        systemLog.setSourceIp(accessAddressUtil.getIpAddress(request));
        String json = readRequestJson(request);
        systemLog.setArgs(json);
        if(null != ShiroUtils.getUser()){
            systemLog.setAddUserName(ShiroUtils.getUser().getUserName());
        }
        insertInterfaceInfo(systemLog);
        return  jdbcTemplateUtils.save(systemLog);
    }

    
    private void insertInterfaceInfo(SystemLog systemLog) throws BusinessException {
    	InterfaceInfo info = new InterfaceInfo();
    	info.setClazz(systemLog.getMethod());
    	info.setModeName(systemLog.getOperationType());
    	info.setServerName(serverName);
       	Object o =  jdbcTemplateUtils.queryOne(info);
       	info.setDesign(designer);
       	if(null == o) {
       		jdbcTemplateUtils.save(info);
       	}
    }
     


    /**
     * @param request
     * @param response
     * @return
     */
    public boolean registerAction(HttpServletRequest request,HttpServletResponse response,String parentUrl) throws BusinessException {
        LumlordApi lumlordApi = new LumlordApi();
        lumlordApi.setMenuUrl(parentUrl);

        LumlordApi menuAction = jdbcTemplateUtils.queryOne(lumlordApi);
        if(menuAction==null){
            throw  new BusinessException("无法找到根 menu ！"+parentUrl);
        }
        lumlordApi.setMenuUrl("NEW_API");
        lumlordApi.setParantId(menuAction.getId());

        HandlerMethod handlerMethod =  jwtAuthFilter.getMethod(request,response);
        if(handlerMethod!=null){
            Api parentApi =  AnnotatedElementUtils.findMergedAnnotation(handlerMethod.getBean().getClass(), Api.class);
            Api api = AnnotatedElementUtils.findMergedAnnotation(handlerMethod.getMethod(), Api.class);
            String name = null;
            if(null != parentApi){
                name = parentApi.moduleName();
            }
            if(null != api){
                name += name==null?api.moduleName():">>"+api.actionName();
                lumlordApi.setMethodName(api.moduleName());
                lumlordApi.setModeName(name);
            }
            lumlordApi.setMethodName(handlerMethod.getMethod().getName());
            lumlordApi.setClazz(handlerMethod.getMethod().toString());
        }

        lumlordApi.setAction(request.getMethod()+":" +request.getRequestURL());

        lumlordApi.setServerName(serverName);
        LumlordApi query = new LumlordApi();
        query.setServerName(serverName);
        query.setClazz(lumlordApi.getClazz());
        query.setMenuUrl(lumlordApi.getMenuUrl());


        LumlordApi  queryObj =  jdbcTemplateUtils.queryOne(query);
        if(queryObj!=null){
            lumlordApi.setId(queryObj.getId());
            return jdbcTemplateUtils.updateById(lumlordApi);
        }

        return  jdbcTemplateUtils.save(lumlordApi);
    }

    private String readRequestJson(HttpServletRequest request) {
        Object obj = request.getAttribute(RequestJsonBody.JSONBODY_ATTRIBUTE);
        return obj != null ? obj.toString() : null;
    }

    /**
     * 插入心跳记录表
     * @return
     */
    private boolean insertHeartBeatLog(HeartbeatLog heartbeatLog) throws BusinessException {
        return jdbcTemplateUtils.save(heartbeatLog);
    }

    /**
     * 插入心跳记录表
     * @param code 方法编号
     * @param arg 协议
     * @param rec 接收对象
     * @param nodeid 节点编号
     * @param resp 消息
     * @param remark 备注
     * @return
     * @throws BusinessException
     */
    public boolean insertHeartBeatLog(String code, String arg, String rec, String nodeid, String resp, String remark) throws BusinessException {
        HeartbeatLog heartbeatLog = new HeartbeatLog();
        heartbeatLog.setCode(code);
        heartbeatLog.setArg(arg);
        heartbeatLog.setRec(rec);
        heartbeatLog.setNodeid(nodeid);
        heartbeatLog.setResp(resp);
        heartbeatLog.setRemark(remark);
        return  insertHeartBeatLog(heartbeatLog);
    }

    /**
     * t_breakdown 强电
     * @param  breakType 故障类型
     * @param breakNodeStatus  节点状态
     * @param   breakLevel  故障等级
     * @param  description 故障原因
     * @param areaId 区域ID
     * @param nodeId 节点ID
     * @param sourceIp 节点IP
     * @return
     */
    public  boolean insertBreakStrongLog(BreakType breakType, BreakLevel breakLevel , BreakNodeStatus breakNodeStatus,Integer areaId,Integer nodeId,String description,String sourceIp) throws BusinessException {
        Breakdown breakdown = new Breakdown();
        breakdown.setType(1);
        //故障类型（1设备故障；2通讯故障；3回路故障；4灯具效果故障；5其他故障）
        breakdown.setBrakType(breakType);
        breakdown.setBrakLevel(breakLevel);
        breakdown.setNodeStatus(breakNodeStatus);
        breakdown.setDescription(description);
        breakdown.setNodeId(nodeId);
        breakdown.setSourceIp(sourceIp);
        breakdown.setAreaId(areaId);
        return  insertBreakLog(breakdown);
    }
    private  boolean insertBreakLog(Breakdown breakdown) throws BusinessException {
        breakdown.setAddDay(DateUtils.format(new Date(),DateUtils.DATE_PATTERN));
        Breakdown ret = jdbcTemplateUtils.queryOne(breakdown);
        if(null != ret){
            return  false;
        }
        //通知 前端 消息
        //webSocket.breakDownNotice(breakdown);
        return  this.jdbcTemplateUtils.save(breakdown);
    }
    /**
     * t_breakdown 弱电
     * @param  breakType 故障类型
     * @param breakNodeStatus  节点状态
     * @param   breakLevel  故障等级
     * @param  description 故障原因
     * @return
     */
    public  boolean insertBreakWeekLog(BreakType breakType, BreakLevel breakLevel , BreakNodeStatus breakNodeStatus,Integer areaId,Integer nodeId,String description,String sourceIp) throws BusinessException {
        Breakdown breakdown = new Breakdown();
        breakdown.setType(2);
        //故障类型（1设备故障；2通讯故障；3回路故障；4灯具效果故障；5其他故障）
        breakdown.setBrakType(breakType);
        breakdown.setBrakLevel(breakLevel);
        breakdown.setNodeStatus(breakNodeStatus);
        breakdown.setDescription(description);
        breakdown.setNodeId(nodeId);
        breakdown.setSourceIp(sourceIp);
        breakdown.setAreaId(areaId);
        return  insertBreakLog(breakdown);
    }
    @Autowired
    private JdbcTemplateUtils jdbcTemplateUtils;
    @Autowired
    private JwtAuthFilter jwtAuthFilter;

   // @Autowired
   // private WebSocket webSocket;
    @Autowired
    private AccessAddressUtil accessAddressUtil;
    @Value("${lumlord.appName}")
    private String serverName;
    @Value("${lumlord.designer}")
    private String designer;
}
